package com.ews.onlineexchange.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.collections.MapUtils;

import com.ews.onlineexchange.model.Trade;
import com.ews.onlineexchange.model.assess.CreditLevel;

public class RandomChooseService {
		
	public static final int[] WEIGHT_ARRAY = new int[] {9, 14, 17, 19, 20, 21};
	public static final CreditLevel[] LEVEL_ARRAY = new CreditLevel[] {CreditLevel.C,CreditLevel.CPlus,CreditLevel.B,CreditLevel.BPlus,CreditLevel.A,CreditLevel.APlus};
	public static final String[] LEVEL_LABEL = new String[] {"C","C+","B","B+","A","A+"};
	TreeMap<Integer, Integer> weightCountMap = new TreeMap<>();
	Map<Integer, List<Trade>> weightGroupTradeMap = new HashMap<>();
	
	public Trade getRandomTrade( List<Trade> trades ) {
		weightGroupTradeMap = new HashMap<>();
		weightCountMap = new TreeMap<>();
		initMap( trades );
		TreeMap<Integer, Integer> weightCountMap = this.weightCountMap;
		int randomWeight = getRandomWeight( trades );
		int randomPos = (int) (Math.random() * weightCountMap.get( randomWeight ) );
		return weightGroupTradeMap.get( randomWeight ).get( randomPos );
	}
	
	private int getRandomWeight( List<Trade> trades ) {
		long max = getRandomLimit( trades );
		int randomInt = (int) (Math.random() * max);
		TreeMap<Integer, Integer> weightCountMap = this.weightCountMap;
		for ( int j = 0; j < WEIGHT_ARRAY.length; j++ ) {
			Integer weightCount = weightCountMap.get( WEIGHT_ARRAY[j] );
			if(weightCount == null) weightCount = 0;
			randomInt = randomInt - WEIGHT_ARRAY[j] * weightCount;
			if ( randomInt < 0 ) {
				return WEIGHT_ARRAY[j];
			}
		}
		throw new RuntimeException();
	}
	
	private long getRandomLimit( List<Trade> trades ) {
		long max = 0l;
		for ( Trade trade : trades ) {
			max += trade.getSupplier().getWeight();
		}
		return max;
	}
	
	private void initMap( List<Trade> trades ) {		
		for ( Trade trade : trades ) {
			Integer key = trade.getSupplier().getWeight();
			Integer value = MapUtils.getInteger( weightCountMap, key, 0 );
			value = value + 1;
			weightCountMap.put( key, value );
			
			List<Trade> weightGroupTradeList = (List<Trade>) MapUtils.getObject( weightGroupTradeMap, key, new ArrayList<>() );
			weightGroupTradeList.add( trade );
			weightGroupTradeMap.put( key, weightGroupTradeList );
		}
	}
	
}
